home *** CD-ROM | disk | FTP | other *** search
/ ShareWare OnLine 2 / ShareWare OnLine Volume 2 (CMS Software)(1993).iso / os2 / elvis172.zip / tmp.c < prev    next >
C/C++ Source or Header  |  1993-03-28  |  18KB  |  792 lines

  1. /* tmp.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains functions which create & readback a TMPFILE */
  12.  
  13.  
  14. #include "config.h"
  15. #include "vi.h"
  16. #if TOS
  17. # include <stat.h>
  18. #else
  19. # if OSK
  20. #  include "osk.h"
  21. # else
  22. #  if AMIGA
  23. #   include "amistat.h"
  24. #  else
  25. #   include <sys/stat.h>
  26. #  endif
  27. # endif
  28. #endif
  29. #if TURBOC
  30. # include <process.h>
  31. #endif
  32.  
  33. #ifndef NO_MODELINES
  34. static void do_modelines(l, stop)
  35.     long    l;    /* line number to start at */
  36.     long    stop;    /* line number to stop at */
  37. {
  38.     char    *str;    /* used to scan through the line */
  39.     char    *start;    /* points to the start of the line */
  40.     char    buf[80];
  41.  
  42.     /* if modelines are disabled, then do nothing */
  43.     if (!*o_modelines)
  44.     {
  45.         return;
  46.     }
  47.  
  48.     /* for each line... */
  49.     for (; l <= stop; l++)
  50.     {
  51.         /* for each position in the line.. */
  52.         for (str = fetchline(l); *str; str++)
  53.         {
  54.             /* if it is the start of a modeline command... */
  55.             if ((str[0] == 'e' && str[1] == 'x'
  56.               || str[0] == 'v' && str[1] == 'i')
  57.               && str[2] == ':')
  58.             {
  59.                 start = str += 3;
  60.  
  61.                 /* find the end */
  62.                 for (str = start + strlen(start); *--str != ':'; )
  63.                 {
  64.                 }
  65.  
  66.                 /* if it is a well-formed modeline, execute it */
  67.                 if (str > start && str - start < sizeof buf)
  68.                 {
  69.                     strncpy(buf, start, (int)(str - start));
  70.                     exstring(buf, str - start, '\\');
  71.                     break;
  72.                 }
  73.             }
  74.         }
  75.     }
  76. }
  77. #endif
  78.  
  79.  
  80. /* The FAIL() macro prints an error message and then exits. */
  81. #define FAIL(why,arg)    mode = MODE_EX; msg(why, arg); endwin(); exit(9)
  82.  
  83. /* This is the name of the temp file */
  84. static char    tmpname[80];
  85.  
  86. /* This function creates the temp file and copies the original file into it.
  87.  * Returns if successful, or stops execution if it fails.
  88.  */
  89. int tmpstart(filename)
  90.     char        *filename; /* name of the original file */
  91. {
  92.     int        origfd;    /* fd used for reading the original file */
  93.     struct stat    statb;    /* stat buffer, used to examine inode */
  94.     REG BLK        *this;    /* pointer to the current block buffer */
  95.     REG BLK        *next;    /* pointer to the next block buffer */
  96.     int        inbuf;    /* number of characters in a buffer */
  97.     int        nread;    /* number of bytes read */
  98.     REG int        j, k;
  99.     int        i;
  100.     long        nbytes;
  101.  
  102.     /* switching to a different file certainly counts as a change */
  103.     changes++;
  104.     redraw(MARK_UNSET, FALSE);
  105.  
  106.     /* open the original file for reading */
  107.     *origname = '\0';
  108.     if (filename && *filename)
  109.     {
  110.         strcpy(origname, filename);
  111.         origfd = open(origname, O_RDONLY);
  112.         if (origfd < 0 && errno != ENOENT)
  113.         {
  114.             msg("Can't open \"%s\"", origname);
  115.             return tmpstart("");
  116.         }
  117.         if (origfd >= 0)
  118.         {
  119.             if (stat(origname, &statb) < 0)
  120.             {
  121.                 FAIL("Can't stat \"%s\"", origname);
  122.             }
  123. #if TOS
  124.             if (origfd >= 0 && (statb.st_mode & S_IJDIR))
  125. #else
  126. # if OSK
  127.             if (origfd >= 0 && (statb.st_mode & S_IFDIR))
  128. # else
  129.             if (origfd >= 0 && (statb.st_mode & S_IFMT) != S_IFREG)
  130. # endif
  131. #endif
  132.             {
  133.                 msg("\"%s\" is not a regular file", origname);
  134.                 return tmpstart("");
  135.             }
  136.         }
  137.         else
  138.         {
  139.             stat(".", &statb);
  140.         }
  141.         if (origfd >= 0)
  142.         {
  143.             origtime = statb.st_mtime;
  144. #if OSK
  145.             if (*o_readonly || !(statb.st_mode &
  146.                   ((getuid() >> 16) == 0 ? S_IOWRITE | S_IWRITE :
  147.                   ((statb.st_gid != (getuid() >> 16) ? S_IOWRITE : S_IWRITE)))))
  148. #endif
  149. #if AMIGA || MSDOS || OS2
  150.             if (*o_readonly || !(statb.st_mode & S_IWRITE))
  151. #endif
  152. #if TOS
  153. # ifdef __GNUC__ 
  154.             if (*o_readonly || !(statb.st_mode & S_IWRITE))
  155. # else
  156.             if (*o_readonly || (statb.st_mode & S_IJRON))
  157. # endif
  158. #endif
  159. #if ANY_UNIX
  160.             if (*o_readonly || !(statb.st_mode &
  161.                   ((geteuid() == 0) ? 0222 :
  162.                   ((statb.st_uid != geteuid() ? 0022 : 0200)))))
  163. #endif
  164. #if VMS
  165.             if (*o_readonly)
  166. #endif
  167.             {
  168.                 setflag(file, READONLY);
  169.             }
  170.         }
  171.         else
  172.         {
  173.             origtime = 0L;
  174.         }
  175.     }
  176.     else
  177.     {
  178.         setflag(file, NOFILE);
  179.         origfd = -1;
  180.         origtime = 0L;
  181.         stat(".", &statb);
  182.     }
  183.  
  184.     /* make a name for the tmp file */
  185.     do
  186.     {
  187.         tmpnum++;
  188. #if MSDOS || TOS || OS2
  189.         /* MS-Dos doesn't allow multiple slashes, but supports drives
  190.          * with current directories.
  191.          * This relies on TMPNAME beginning with "%s\\"!!!!
  192.          */
  193.         strcpy(tmpname, o_directory);
  194.         if ((i = strlen(tmpname)) && !strchr(":/\\", tmpname[i-1]))
  195.             tmpname[i++]=SLASH;
  196.         sprintf(tmpname+i, TMPNAME+3, getpid(), tmpnum);
  197. #else
  198.         sprintf(tmpname, TMPNAME, o_directory, getpid(), tmpnum);
  199. #endif
  200.     } while (access(tmpname, 0) == 0);
  201.  
  202.     /* !!! RACE CONDITION HERE - some other process with the same PID could
  203.      * create the temp file between the access() call and the creat() call.
  204.      * This could happen in a couple of ways:
  205.      * - different workstation may share the same temp dir via NFS.  Each
  206.      *   workstation could have a process with the same number.
  207.      * - The DOS version may be running multiple times on the same physical
  208.      *   machine in different virtual machines.  The DOS pid number will
  209.      *   be the same on all virtual machines.
  210.      *
  211.      * This race condition could be fixed by replacing access(tmpname, 0)
  212.      * with open(tmpname, O_CREAT|O_EXCL, 0600), if we could only be sure
  213.      * that open() *always* used modern UNIX semantics.
  214.      */
  215.  
  216.     /* create the temp file */
  217. #if ANY_UNIX
  218.     close(creat(tmpname, 0600));        /* only we can read it */
  219. #else
  220.     close(creat(tmpname, FILEPERMS));    /* anybody body can read it, alas */
  221. #endif
  222.     tmpfd = open(tmpname, O_RDWR | O_BINARY);
  223.     if (tmpfd < 0)
  224.     {
  225.         FAIL("Can't create temp file... Does directory \"%s\" exist?", o_directory);
  226.         return 1;
  227.     }
  228.  
  229.     /* allocate space for the header in the file */
  230.     if (write(tmpfd, hdr.c, (unsigned)BLKSIZE) < BLKSIZE
  231.      || write(tmpfd, tmpblk.c, (unsigned)BLKSIZE) < BLKSIZE)
  232.     {
  233.         FAIL("Error writing headers to \"%s\"", tmpname);
  234.     }
  235.  
  236. #ifndef NO_RECYCLE
  237.     /* initialize the block allocator */
  238.     /* This must already be done here, before the first attempt
  239.      * to write to the new file! GB */
  240.     garbage();
  241. #endif
  242.  
  243.     /* initialize lnum[] */
  244.     for (i = 1; i < MAXBLKS; i++)
  245.     {
  246.         lnum[i] = INFINITY;
  247.     }
  248.     lnum[0] = 0;
  249.  
  250.     /* if there is no original file, then create a 1-line file */
  251.     if (origfd < 0)
  252.     {
  253.         hdr.n[0] = 0;    /* invalid inode# denotes new file */
  254.  
  255.         this = blkget(1);     /* get the new text block */
  256.         strcpy(this->c, "\n");    /* put a line in it */
  257.  
  258.         lnum[1] = 1L;    /* block 1 ends with line 1 */
  259.         nlines = 1L;    /* there is 1 line in the file */
  260.         nbytes = 1L;
  261.  
  262.         if (*origname)
  263.         {
  264.             msg("\"%s\" [NEW FILE]  1 line, 1 char", origname);
  265.         }
  266.         else
  267.         {
  268.             msg("\"[NO FILE]\"  1 line, 1 char");
  269.         }
  270.     }
  271.     else /* there is an original file -- read it in */
  272.     {
  273.         nbytes = nlines = 0;
  274.  
  275.         /* preallocate 1 "next" buffer */
  276.         i = 1;
  277.         next = blkget(i);
  278.         inbuf = 0;
  279.  
  280.         /* loop, moving blocks from orig to tmp */
  281.         for (;;)
  282.         {
  283.             /* "next" buffer becomes "this" buffer */
  284.             this = next;
  285.  
  286.             /* read [more] text into this block */
  287.             nread = tread(origfd, &this->c[inbuf], BLKSIZE - 1 - inbuf);
  288.             if (nread < 0)
  289.             {
  290.                 close(origfd);
  291.                 close(tmpfd);
  292.                 tmpfd = -1;
  293.                 unlink(tmpname);
  294.                 FAIL("Error reading \"%s\"", origname);
  295.             }
  296.  
  297.             /* convert NUL characters to something else */
  298.             for (j = k = inbuf; k < inbuf + nread; k++)
  299.             {
  300.                 if (!this->c[k])
  301.                 {
  302.                     setflag(file, HADNUL);
  303.                     this->c[j++] = 0x80;
  304.                 }
  305. #ifndef CRUNCH
  306.                 else if (*o_beautify && this->c[k] < ' ' && this->c[k] >= 1)
  307.                 {
  308.                     if (this->c[k] == '\t'
  309.                      || this->c[k] == '\n'
  310.                      || this->c[k] == '\f')
  311.                     {
  312.                         this->c[j++] = this->c[k];
  313.                     }
  314.                     else if (this->c[k] == '\b')
  315.                     {
  316.                         /* delete '\b', but complain */
  317.                         setflag(file, HADBS);
  318.                     }
  319.                     /* else silently delete control char */
  320.                 }
  321. #endif
  322.                 else
  323.                 {
  324.                     this->c[j++] = this->c[k];
  325.                 }
  326.             }
  327.             inbuf = j;
  328.  
  329.             /* if the buffer is empty, quit */
  330.             if (inbuf == 0)
  331.             {
  332.                 goto FoundEOF;
  333.             }
  334.  
  335. #if MSDOS || TOS || OS2
  336. /* BAH! MS text mode read fills inbuf, then compresses eliminating \r
  337.    but leaving garbage at end of buf. The same is true for TURBOC. GB. */
  338.  
  339.             memset(this->c + inbuf, '\0', BLKSIZE - inbuf);
  340. #endif
  341.  
  342.             /* search backward for last newline */
  343.             for (k = inbuf; --k >= 0 && this->c[k] != '\n';)
  344.             {
  345.             }
  346.             if (k++ < 0)
  347.             {
  348.                 if (inbuf >= BLKSIZE - 1)
  349.                 {
  350.                     k = 80;
  351.                 }
  352.                 else
  353.                 {
  354.                     k = inbuf;
  355.                 }
  356.             }
  357.  
  358.             /* allocate next buffer */
  359.             if (i >= MAXBLKS - 2)
  360.             {
  361.                 FAIL("File too big.  Limit is approx %ld kbytes.", MAXBLKS * BLKSIZE / 1024L);
  362.             }
  363.             next = blkget(++i);
  364.  
  365.             /* move fragmentary last line to next buffer */
  366.             inbuf -= k;
  367.             for (j = 0; k < BLKSIZE; j++, k++)
  368.             {
  369.                 next->c[j] = this->c[k];
  370.                 this->c[k] = 0;
  371.             }
  372.  
  373.             /* if necessary, add a newline to this buf */
  374.             for (k = BLKSIZE - inbuf; --k >= 0 && !this->c[k]; )
  375.             {
  376.             }
  377.             if (this->c[k] != '\n')
  378.             {
  379.                 setflag(file, ADDEDNL);
  380.                 this->c[k + 1] = '\n';
  381.             }
  382.  
  383.             /* count the lines in this block */
  384.             for (k = 0; k < BLKSIZE && this->c[k]; k++)
  385.             {
  386.                 if (this->c[k] == '\n')
  387.                 {
  388.                     nlines++;
  389.                 }
  390.                 nbytes++;
  391.             }
  392.             lnum[i - 1] = nlines;
  393.         }
  394. FoundEOF:
  395.  
  396.         /* if this is a zero-length file, add 1 line */
  397.         if (nlines == 0)
  398.         {
  399.             this = blkget(1);     /* get the new text block */
  400.             strcpy(this->c, "\n");    /* put a line in it */
  401.  
  402.             lnum[1] = 1;    /* block 1 ends with line 1 */
  403.             nlines = 1;    /* there is 1 line in the file */
  404.             nbytes = 1;
  405.         }
  406.  
  407. #if MSDOS || TOS || OS2
  408.         /* each line has an extra CR that we didn't count yet */
  409.         nbytes += nlines;
  410. #endif
  411.  
  412.         /* report the number of lines in the file */
  413.         msg("\"%s\" %s %ld line%s, %ld char%s",
  414.             origname,
  415.             (tstflag(file, READONLY) ? "[READONLY]" : ""),
  416.             nlines,
  417.             nlines == 1 ? "" : "s",
  418.             nbytes,
  419.             nbytes == 1 ? "" : "s");
  420.     }
  421.  
  422.     /* initialize the cursor to start of line 1 */
  423.     cursor = MARK_FIRST;
  424.  
  425.     /* close the original file */
  426.     close(origfd);
  427.  
  428.     /* any other messages? */
  429.     if (tstflag(file, HADNUL))
  430.     {
  431.         msg("This file contained NULs.  They've been changed to \\x80 chars");
  432.     }
  433.     if (tstflag(file, ADDEDNL))
  434.     {
  435.         msg("Newline characters have been inserted to break up long lines");
  436.     }
  437. #ifndef CRUNCH
  438.     if (tstflag(file, HADBS))
  439.     {
  440.         msg("Backspace characters deleted due to ':set beautify'");
  441.     }
  442. #endif
  443.  
  444.     storename(origname);
  445.  
  446. #ifndef NO_MODELINES
  447.     if (nlines > 10)
  448.     {
  449.         do_modelines(1L, 5L);
  450.         do_modelines(nlines - 4L, nlines);
  451.     }
  452.     else
  453.     {
  454.         do_modelines(1L, nlines);
  455.     }
  456. #endif
  457.  
  458.     /* force all blocks out onto the disk, to support file recovery */
  459.     blksync();
  460.  
  461.     return 0;
  462. }
  463.  
  464.  
  465.  
  466. /* This function copies the temp file back onto an original file.
  467.  * Returns TRUE if successful, or FALSE if the file could NOT be saved.
  468.  */
  469. int tmpsave(filename, bang)
  470.     char    *filename;    /* the name to save it to */
  471.     int    bang;        /* forced write? */
  472. {
  473.     int        fd;    /* fd of the file we're writing to */
  474.     REG int        len;    /* length of a text block */
  475.     REG BLK        *this;    /* a text block */
  476.     long        bytes;    /* byte counter */
  477.     REG int        i;
  478.  
  479.     /* if no filename is given, assume the original file name */
  480.     if (!filename || !*filename)
  481.     {
  482.         filename = origname;
  483.     }
  484.  
  485.     /* if still no file name, then fail */
  486.     if (!*filename)
  487.     {
  488.         msg("Don't know a name for this file -- NOT WRITTEN");
  489.         return FALSE;
  490.     }
  491.  
  492.     /* can't rewrite a READONLY file */
  493.     if (!strcmp(filename, origname) && tstflag(file, READONLY) && !bang)
  494.     {
  495.         msg("\"%s\" [READONLY] -- NOT WRITTEN", filename);
  496.         return FALSE;
  497.     }
  498.  
  499.     /* open the file */
  500.     if (*filename == '>' && filename[1] == '>')
  501.     {
  502.         filename += 2;
  503.         while (*filename == ' ' || *filename == '\t')
  504.         {
  505.             filename++;
  506.         }
  507. #ifdef O_APPEND
  508.         fd = open(filename, O_WRONLY|O_APPEND);
  509. #else
  510.         fd = open(filename, O_WRONLY);
  511.         lseek(fd, 0L, 2);
  512. #endif
  513.     }
  514.     else
  515.     {
  516.         /* either the file must not exist, or it must be the original
  517.          * file, or we must have a bang, or "writeany" must be set.
  518.          */
  519.         if (strcmp(filename, origname) && access(filename, 0) == 0 && !bang
  520. #ifndef CRUNCH
  521.             && !*o_writeany
  522. #endif
  523.                    )
  524.         {
  525.             msg("File already exists - Use :w! to overwrite");
  526.             return FALSE;
  527.         }
  528. #if VMS
  529.         /* Create a new VMS version of this file. */
  530.         { 
  531.         char *strrchr(), *ptr = strrchr(filename,';');
  532.         if (ptr) *ptr = '\0';  /* Snip off any ;number in the name */
  533.         }
  534. #endif
  535.         fd = creat(filename, FILEPERMS);
  536.     }
  537.     if (fd < 0)
  538.     {
  539.         msg("Can't write to \"%s\" -- NOT WRITTEN", filename);
  540.         return FALSE;
  541.     }
  542.  
  543.     /* write each text block to the file */
  544.     bytes = 0L;
  545.     for (i = 1; i < MAXBLKS && (this = blkget(i)) && this->c[0]; i++)
  546.     {
  547.         for (len = 0; len < BLKSIZE && this->c[len]; len++)
  548.         {
  549.         }
  550.         if (twrite(fd, this->c, len) < len)
  551.         {
  552.             msg("Trouble writing to \"%s\"", filename);
  553.             if (!strcmp(filename, origname))
  554.             {
  555.                 setflag(file, MODIFIED);
  556.             }
  557.             close(fd);
  558.             return FALSE;
  559.         }
  560.         bytes += len;
  561.     }
  562.  
  563.     /* reset the "modified" flag, but not the "undoable" flag */
  564.     clrflag(file, MODIFIED);
  565.     significant = FALSE;
  566.     if (!strcmp(origname, filename))
  567.     {
  568.         exitcode &= ~1;
  569.     }
  570.  
  571.     /* report lines & characters */
  572. #if MSDOS || TOS || OS2
  573.     bytes += nlines; /* for the inserted carriage returns */
  574. #endif
  575.     msg("Wrote \"%s\"  %ld lines, %ld characters", filename, nlines, bytes);
  576.  
  577.     /* close the file */
  578.     close(fd);
  579.  
  580.     return TRUE;
  581. }
  582.  
  583.  
  584. /* This function deletes the temporary file.  If the file has been modified
  585.  * and "bang" is FALSE, then it returns FALSE without doing anything; else
  586.  * it returns TRUE.
  587.  *
  588.  * If the "autowrite" option is set, then instead of returning FALSE when
  589.  * the file has been modified and "bang" is false, it will call tmpend().
  590.  */
  591. int tmpabort(bang)
  592.     int    bang;
  593. {
  594.     /* if there is no file, return successfully */
  595.     if (tmpfd < 0)
  596.     {
  597.         return TRUE;
  598.     }
  599.  
  600.     /* see if we must return FALSE -- can't quit */
  601.     if (!bang && tstflag(file, MODIFIED))
  602.     {
  603.         /* if "autowrite" is set, then act like tmpend() */
  604.         if (*o_autowrite)
  605.             return tmpend(bang);
  606.         else
  607.             return FALSE;
  608.     }
  609.  
  610.     /* delete the tmp file */
  611.     cutswitch();
  612.     strcpy(prevorig, origname);
  613.     prevline = markline(cursor);
  614.     *origname = '\0';
  615.     origtime = 0L;
  616.     blkinit();
  617.     nlines = 0;
  618.     initflags();
  619.     return TRUE;
  620. }
  621.  
  622. /* This function saves the file if it has been modified, and then deletes
  623.  * the temporary file. Returns TRUE if successful, or FALSE if the file
  624.  * needs to be saved but can't be.  When it returns FALSE, it will not have
  625.  * deleted the tmp file, either.
  626.  */
  627. int tmpend(bang)
  628.     int    bang;
  629. {
  630.     /* save the file if it has been modified */
  631.     if (tstflag(file, MODIFIED) && !tmpsave((char *)0, FALSE) && !bang)
  632.     {
  633.         return FALSE;
  634.     }
  635.  
  636.     /* delete the tmp file */
  637.     tmpabort(TRUE);
  638.  
  639.     return TRUE;
  640. }
  641.  
  642.  
  643. /* If the tmp file has been changed, then this function will force those
  644.  * changes to be written to the disk, so that the tmp file will survive a
  645.  * system crash or power failure.
  646.  */
  647. #if AMIGA || MSDOS || TOS || OS2
  648. sync()
  649. {
  650.     /* MS-DOS and TOS don't flush their buffers until the file is closed,
  651.      * so here we close the tmp file and then immediately reopen it.
  652.      */
  653.     close(tmpfd);
  654.     tmpfd = open(tmpname, O_RDWR | O_BINARY);
  655.     return 0;
  656. }
  657. #endif
  658.  
  659.  
  660. /* This function stores the file's name in the second block of the temp file.
  661.  * SLEAZE ALERT!  SLEAZE ALERT!  The "tmpblk" buffer is probably being used
  662.  * to store the arguments to a command, so we can't use it here.  Instead,
  663.  * we'll borrow the buffer that is used for "shift-U".
  664.  */
  665. int
  666. storename(name)
  667.     char    *name;    /* the name of the file - normally origname */
  668. {
  669. #ifndef CRUNCH
  670.     int    len;
  671.     char    *ptr;
  672. #endif
  673.  
  674.     /* we're going to clobber the U_text buffer, so reset U_line */
  675.     U_line = 0L;
  676.  
  677.     if (!name)
  678.     {
  679.         strncpy(U_text, "", BLKSIZE);
  680.         U_text[1] = 127;
  681.     }
  682. #ifndef CRUNCH
  683. # if TOS || MINT || MSDOS || AMIGA || OS2
  684.     else if (*name != '/' && *name != '\\' && !(*name && name[1] == ':'))
  685. # else
  686.     else if (*name != SLASH)
  687. # endif
  688.     {
  689.         /* get the directory name */
  690.         ptr = getcwd(U_text, BLKSIZE);
  691.         if (ptr != U_text)
  692.         {
  693.             strcpy(U_text, ptr);
  694.         }
  695.  
  696.         /* append a slash to the directory name */
  697.         len = strlen(U_text);
  698.         U_text[len++] = SLASH;
  699.  
  700.         /* append the filename, padded with heaps o' NULs */
  701.         strncpy(U_text + len, *name ? name : "foo", BLKSIZE - len);
  702.     }
  703. #endif
  704.     else
  705.     {
  706.         /* copy the filename into U_text */
  707.         strncpy(U_text, *name ? name : "foo", BLKSIZE);
  708.     }
  709.  
  710.     if (tmpfd >= 0)
  711.     {
  712.         /* write the name out to second block of the temp file */
  713.         lseek(tmpfd, (long)BLKSIZE, 0);
  714.         if (write(tmpfd, U_text, (unsigned)BLKSIZE) < BLKSIZE)
  715.         {
  716.             FAIL("Error stuffing name \"%s\" into temp file", U_text);
  717.         }
  718.     }
  719.     return 0;
  720. }
  721.  
  722.  
  723.  
  724. /* This function handles deadly signals.  It restores sanity to the terminal
  725.  * preserves the current temp file, and deletes any old temp files.
  726.  */
  727. SIGTYPE deathtrap(sig)
  728.     int    sig;    /* the deadly signal that we caught */
  729. {
  730.     char    *why;
  731.  
  732.     /* restore the terminal's sanity */
  733.     endwin();
  734.  
  735. #ifdef CRUNCH
  736.     why = "-Elvis died";
  737. #else
  738.     /* give a more specific description of how Elvis died */
  739.     switch (sig)
  740.     {
  741. # ifdef SIGHUP
  742.       case SIGHUP:    why = "-the modem lost its carrier";        break;
  743. # endif
  744. # ifndef DEBUG
  745. #  ifdef SIGILL
  746.       case SIGILL:    why = "-Elvis hit an illegal instruction";    break;
  747. #  endif
  748. #  ifdef SIGBUS
  749.       case SIGBUS:    why = "-Elvis had a bus error";            break;
  750. #  endif
  751. #  ifdef SIGSEGV
  752. #   if !TOS
  753.       case SIGSEGV:    why = "-Elvis had a segmentation violation";    break;
  754. #   endif
  755. #  endif
  756. #  ifdef SIGSYS
  757.       case SIGSYS:    why = "-Elvis munged a system call";        break;
  758. #  endif
  759. # endif /* !DEBUG */
  760. # ifdef SIGPIPE
  761.       case SIGPIPE:    why = "-the pipe reader died";            break;
  762. # endif
  763. # ifdef SIGTERM
  764.       case SIGTERM:    why = "-Elvis was terminated";            break;
  765. # endif
  766. # if !MINIX
  767. #  ifdef SIGUSR1
  768.       case SIGUSR1:    why = "-Elvis was killed via SIGUSR1";        break;
  769. #  endif
  770. #  ifdef SIGUSR2
  771.       case SIGUSR2:    why = "-Elvis was killed via SIGUSR2";        break;
  772. #  endif
  773. # endif
  774.       default:    why = "-Elvis died";                break;
  775.     }
  776. #endif
  777.  
  778.     /* if we had a temp file going, then preserve it */
  779.     if (tmpnum > 0 && tmpfd >= 0)
  780.     {
  781.         close(tmpfd);
  782.         sprintf(tmpblk.c, "%s \"%s\" %s", PRESERVE, why, tmpname);
  783.         system(tmpblk.c);
  784.     }
  785.  
  786.     /* delete any old temp files */
  787.     cutend();
  788.  
  789.     /* exit with the proper exit status */
  790.     exit(sig);
  791. }
  792.